// 这里实现标签页的切换

function initSwitchTab() {
    // 1.先获取相关的元素
    let tabSession = document.querySelector('.tab .tab-session')
    let tabFriend = document.querySelector('.tab .tab-friend');
    // querySelectorAll() 可以同时选中多个元素, 得到的结果是一个数组
    // [0]是会话列表
    // [1]是好友列表
    let lists = document.querySelectorAll('.list');
    // 2.针对标签页按钮注册点击事件
    tabSession.onclick = function() {
        // 设置图标
        tabSession.style.backgroundImage = 'url(img/会话.png)';
        tabFriend.style.backgroundImage = 'url(img/用户2.png)';
        // 显示会话列表, 隐藏好友列表
        lists[0].classList = 'list';
        lists[1].classList = 'list hide';
    }
    tabFriend.onclick = function() {
        // 设置图标
        tabSession.style.backgroundImage = 'url(img/会话2.png)';
        tabFriend.style.backgroundImage = 'url(img/用户.png)';
        // 显示好友列表, 隐藏会话列表
        lists[1].classList = 'list';
        lists[0].classList = 'list hide';
    }
}

initSwitchTab();

////////////////////////////////////////////////////////
// 操作 websocket
////////////////////////////////////////////////////////

// 创建 websocket 实例
// let websocket = new WebSocket("ws://127.0.0.1:8080/WebSocketMessage");
let websocket = new WebSocket("ws://" + location.host + "/WebSocketMessage");
websocket.onopen = function() {
    // 连接建立完成后, 就会自动执行到
    console.log("websocket 连接成功!");
}
websocket.onclose = function() {
    // 连接断开后, 自动执行到
    console.log("websocket 连接关闭!");
}
websocket.onerror = function() {
    console.log("websocket 连接异常!");
}
websocket.onmessage = function(message) {
    console.log("websocket 收到消息: " + message.data);
    // 此时收到的 message.data 是个 JSON 字符串, 需要转成 js 对象
    let resp = JSON.parse(message.data);
    if (resp.type == 'message') {
        // 处理消息响应
        handleMessage(resp);
    } else {
        // 响应的 type 出错
        console.log("resp.type 非法类型!")
    }
}

/**
 * 把客户端收到的消息给展示出来
 * 展示到对应的会话预览区域, 以及右侧消息列表中(如果是被选中状态).
 * @param {*} resp 
 */
function handleMessage(resp) {
    // 1. 根据响应中的 sessionId 获取到当前对话的 li 标签
    //    如果 li 标签不存在, 则创建一个新的
    let curSessionLi = findSessionLi(resp.sessionId);
    if (curSessionLi == null) {
        // 需要创建出新的 li 标签, 来表示新的会话
        curSessionLi = document.createElement('li');
        curSessionLi.setAttribute('message-session-id', resp.sessionId);
        curSessionLi.innerHTML = '<h3>' + resp.fromName + '</h3>' + 
            '<p></p>';
        // 给这个 li 标签也加上点击事件的处理
        curSessionLi.onclick = function() {
            clickSession(curSessionLi);
        }
    }
    // 2. 把新消息显示到会话预览区域 (li 标签中的 p 标签中)
    //    如果消息太长需要截断
    let p = curSessionLi.querySelector('p');
    p.innerHTML = resp.content;
    if (p.innerHTML.length > 10) {
        p.innerHTML = p.innerHTML.substring(0, 10) + '...';
    }
    // 3. 把收到消息的会话, 给放到消息列表的最上方.
    let sessionListUL = document.querySelector('#session-list');
    sessionListUL.insertBefore(curSessionLi, sessionListUL.children[0]);
    // 4. 如果当前收到的会话属于被选中状态, 则当前的消息放入到右侧的消息列表中.
    //    新增消息的同时调整滚动条的位置, 保证新消息在底部
    if (curSessionLi.className == 'selected') {
        // 把消息列表添加一个新消息
        let messageShowDiv = document.querySelector('.right .message-show');
        addMessage(messageShowDiv, resp);
        scrollBottom(messageShowDiv);
    }
    // 其他操作
}

function findSessionLi(targetSessionId) {
    let sessionLis = document.querySelectorAll('#session-list li');
    for (let li of sessionLis) {
        let sessionId = li.getAttribute('message-session-id');
        if (sessionId == targetSessionId) {
            return li;
        }
    }
    return null;
}



////////////////////////////////////////////////////////
// 实现消息发送/接受逻辑
////////////////////////////////////////////////////////

function initSendButton() {
    // 1. 获取到发送按钮和输入框
    let sendButton = document.querySelector('.right .ctrl button');
    let messageInput = document.querySelector('.right .message-input');
    // 2. 给发送按钮注册一个点击事件
    sendButton.onclick = function() {
        if (!messageInput.value) {
            // value 的值是 null 或者 '' 都会触发这个条件
            console.log('消息框中内容为空!');
            return;
        }
        // 获取当前选中的 li 标签的 sessionId
        let selectedLi = document.querySelector('#session-list .selected');
        if (selectedLi == null) {
            console.log('没有标签被选中!');
            return;
        }
        let sessionId = selectedLi.getAttribute('message-session-id');
        // 构造 json 数据
        let req = {
            type: 'message',
            sessionId: sessionId,
            content: messageInput.value
        };
        // 通过 websocket 发送数据
        req = JSON.stringify(req);
        console.log("[websocket] send: " + req);
        websocket.send(req);
        // 发送完成后, 把输入框清空
        messageInput.value = '';
    }
}
initSendButton();


////////////////////////////////////////////////////////
// 从服务器获取到当前用户登录数据
////////////////////////////////////////////////////////


function getUserInfo() {
    $.ajax({
        url: '/userInfo',
        type: 'get',
        success: function(body) {
            if (body.userId > 0) {
                let userDIV = document.querySelector('.main .left .user');
                userDIV.innerHTML = body.username;
                userDIV.setAttribute("user-id", body.userId);
            } else {
                // 返回结果无效, 跳转到登陆界面 
                alert("当前用户未登录!");
                location.assign('/login.html');
            }
        }
    });
}

getUserInfo();

// 获取好友列表
function getFriendList() {
    $.ajax({
        type: 'get',
        url: '/friendList',
        success: function(body) {
            // 1. 先把之前的好友列表的内容清空
            let friendListUL = document.querySelector('#friend-list');
            friendListUL.innerHTML = "";
            // 2. 遍历 body 把响应结果加回到 friend-list 中
            for (let friend of body) {
                let li = document.createElement('li');
                li.innerHTML = '<h4>' + friend.friendName + '</h4>';
                li.setAttribute("friend-id", friend.friendId);
                friendListUL.appendChild(li);
                // 每个 li 标签都对应界面上的一个好友选项. 给这个 li 加上点击事件的处理
                li.onclick = function() {
                    // 参数表示当前用户点击的是哪个好友
                    clickFriend(friend);
                }
            }
        },
        error: function(body) {
            console.log('获取好友列表失败');
        }
    });
    
}

getFriendList();

function getSessionList() {
    $.ajax({
        type: 'get',
        url: '/sessionList',
        success: function(body) {
            // 1. 清空之前的会话列表
            let sessionListUL = document.querySelector('#session-list');
            sessionListUL.innerHTML = '';
            // 2. 遍历响应的数组, 针对结果来构造页面
            for (let session of body) {
                // 针对 lastMessage 的长度进行截断处理
                if (session.lastMessage.length > 10) {
                    session.lastMessage = session.lastMessage.subString(0, 10) + '...';
                }
                let li = document.createElement('li');
                li.setAttribute('message-session-id', session.sessionId);
                li.innerHTML = '<h3>' + session.friends[0].friendName + '<h3>' +
                    '<p>' + session.lastMessage + '<p>';
                sessionListUL.append(li);

                // 给 li 标签新增点击事件
                li.onclick = function() {
                    clickSession(li);
                }
            }
        }
    });
}

getSessionList();

function clickSession(currentLi) {
    // 1. 设置高亮
    let allLis = document.querySelectorAll('#session-list>li');
    activeSession(allLis, currentLi);
    // 2. 获取指定会话的历史消息
    let sessionId = currentLi.getAttribute("message-session-id");
    getHistoryMessage(sessionId);
}

function activeSession(allLis, currentLi) {
    for (let li of allLis) {
        if (li == currentLi) {
            li.className = 'selected';
        } else {
            li.className = '';
        }
    }
}

function getHistoryMessage(sessionId) {
    console.log("获取历史消息 sessionId = " + sessionId);
    // 1. 先清空右侧列表中的已有内容
    let titleDiv = document.querySelector('.right .title');
    titleDiv.innerHTML = '';
    let messageShowDiv = document.querySelector('.right .message-show');
    messageShowDiv.innerHTML = '';

    // 2. 重新设置会话的标题, 新的会话标题是点击的那个会话上面显示的的标题
    let selectedH3 = document.querySelector('#session-list .selected>h3');
    if (selectedH3) {
        // selectedH3 可能是不存在的
        titleDiv.innerHTML = selectedH3.innerHTML;
    }
    // 3. 发送 ajax 请求给服务器, 获取该会话的历史消息.
    $.ajax({
        type: 'get',
        url: '/message?sessionId=' + sessionId,
        success: function(body) {
            if (body == null) {
                console.log('返回的历史消息列表为空');
            }
            for (let message of body) {
                addMessage(messageShowDiv, message);
            }
            // 加上这个操作: 在构造好这个消息列表之后, 控制滚动条自动滚到最下方
            scrollBottom(messageShowDiv);
        }
    });
}

function addMessage(messageShowDiv, message) {
    // 使用这个 div 表示一条消息
    let messageDiv = document.createElement('div');
    // 此处需要判断当前的消息是不是自己发的, 来决定靠左还是靠右
    let selfUsername = document.querySelector('.left .user').innerHTML;
    if (selfUsername == message.fromName) {
        // 消息是自己发的 靠右
        messageDiv.className = 'message message-right';
    } else {
        // 消息是别人发的 靠左
        messageDiv.className = 'message message-left';
    }

    // 根据 content 的字数动态设置气泡长度
    let contentLength = message.content.length;
    let width = Math.min(500, contentLength * 12 + 20);

    messageDiv.innerHTML = '<div class="box">' +
        '<h4>' + message.fromName + '</h4>' + 
        '<p>' + message.content + '</p>' +
        '</div>';
    
    messageShowDiv.appendChild(messageDiv);
}

//  把 elem 里面的内容滚动到底部.
function scrollBottom(elem) {
    // 1. 获取到可视区域的高度
    let clientHeight = elem.offsetHeight;
    // 2. 获取到内容的总高度
    let scrollHeight = elem.scrollHeight;
    // 3. 进行滚动操作, 第一个参数是水平方向滚动的尺寸, 第二个参数是垂直方向滚动的尺寸
    elem.scrollTo(0, scrollHeight - clientHeight);
}
// 点击好友列表项触发的函数
function clickFriend(friend) {
    // 1. 先判定一下当前这个好友是否有对应的会话
    let sessionLi = findSessionByName(friend.friendName);
    let sessionUl = document.querySelector('#session-list');
    if (sessionLi) {
        // 2. 当前存在匹配的结果, 就把这个会话设置成选中状态, 并且置顶
        sessionUl.insertBefore(sessionLi, sessionUl.children[0]);
        clickSession(sessionLi);
        // 或者模拟点击
        //sessionLi.click();
    } else {
        // 3. 如果不存在匹配的结果, 就创建个新会话(创建li标签 + 通知服务器)
        sessionLi = document.createElement('li');
        sessionLi.innerHTML = '<h3>' + friend.friendName + '</h3>' + '<p></p>';
        // 把标签置顶
        sessionUl.insertBefore(sessionLi, sessionUl.children[0]);
        sessionLi.onclick = function() {
            clickSession(sessionLi);
        }
        sessionLi.click();
        // 发送给服务器, 告诉服务器当前的会话是啥样的.
        createSession(friend.friendId, sessionLi);

    }

    // 4. 同时把标签页切换到会话列表
    //    实现方式很容易, 只要找到会话列表标签页按钮, 模拟一个点击操作即可
    let tabSession = document.querySelector('.tab .tab-session');
    tabSession.click();
}

function findSessionByName(username) {
    // 先获取到会话列表中所有的 li 标签
    // 依次遍历, 找到名字一致的
    let sessionListLi = document.querySelectorAll('#session-list>li');
    for (let sessionLi of sessionListLi) {
        // 获取 li 标签里的 h3 标签, 进一步得到名字
        let h3 = sessionLi.querySelector('h3');
        if (h3.innerHTML == username) {
            return sessionLi;
        }
    }
    return null;
}

function createSession(friendId, sessionLi) {
    $.ajax({
        type: 'post',
        url: 'session?toUserId=' + friendId,
        success: function(body) {
            console.log("会话创建成功! sessionId = " + body.sessionId);
            sessionLi.setAttribute('message-session-id', body.sessionId);
        },
        error: function(body) {
            console.log("会话创建失败!");
            
        }
    });
}
